package edu.whu.demo.aspect;

import lombok.Data;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Data
public class ApiMetric {

    private AtomicInteger executionCount = new AtomicInteger(0);



    private AtomicInteger maxExecutionTime = new AtomicInteger(Integer.MIN_VALUE);
    private AtomicInteger totalExecutionTime = new AtomicInteger(0);

    private AtomicInteger minExecutionTime = new AtomicInteger(Integer.MAX_VALUE);
    private Map<String, AtomicInteger> exceptionCountMap = Collections.synchronizedMap(new HashMap<>());

    public void addTime(int time) {
        executionCount.incrementAndGet();
        totalExecutionTime.addAndGet(time);
        updateMinExecutionTime(time);
        updateMaxExecutionTime(time);
    }

    private void updateMinExecutionTime(int time) {
        while (true) {
            int currentMin = minExecutionTime.get();

            if (time >= currentMin) {



                break;
            }
            if (minExecutionTime.compareAndSet(currentMin, time)) {

                break;
            }
        }
    }

    private void updateMaxExecutionTime(int time) {
        while (true) {



            int currentMax = maxExecutionTime.get();

            if (time <= currentMax) {

                break;
            }
            if (maxExecutionTime.compareAndSet(currentMax, time)) {

                break;
            }
        }
    }

    public void addException(Throwable e) {

        String exceptionName = e.getClass().getName();

        exceptionCountMap.computeIfAbsent(exceptionName, k -> new AtomicInteger(0)).incrementAndGet();
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();

        builder.append("MaxExecutionTime:").append(maxExecutionTime).append("\n");
        builder.append("ExceptionCounts:\n");
        builder.append("ExecutionCount:").append(executionCount).append("\n");
        builder.append("TotalExecutionTime:").append(totalExecutionTime).append("\n");

        builder.append("AverageExecutionTime:").append((float) totalExecutionTime.get() / executionCount.get()).append("\n");



        builder.append("MinExecutionTime:").append(minExecutionTime).append("\n");

        exceptionCountMap.forEach((e, count) -> {
            builder.append(" ").append(e).append(":").append(count).append("\n");

        });
        return builder.toString();
    }
}
